package com.yungu.swift.lbs.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.Lists;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.lbs.model.param.FenceParam;
import com.yungu.swift.lbs.model.vo.FenceVo;
import com.yungu.swift.lbs.service.FenceService;
import com.yungu.swift.lbs.utils.HttpClient4Utils;
import com.yungu.swift.utils.JsonUtils;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.yungu.swift.lbs.config.NacosListener.THIRDPARTY_CONFIG;

/**
 * @author : cuixiuyin
 * @date : 2019/10/9
 */
@Slf4j
@Service
public class FenceServiceImpl implements FenceService {
    /**
     * 创建/更新圆形围栏
     */
    private static final String CIRCLE_ADD = "https://tsapi.amap.com/v1/track/geofence/add/circle";
    private static final String CIRCLE_UPDATE = "https://tsapi.amap.com/v1/track/geofence/update/circle";
    /**
     * 创建/更新多边形围栏
     */
    private static final String POLYGON_ADD = "https://tsapi.amap.com/v1/track/geofence/add/polygon";
    private static final String POLYGON_UPDATE = "https://tsapi.amap.com/v1/track/geofence/update/polygon";
    /**
     * 删除围栏
     */
    private static final String GEOFENCE_DELETE = "https://tsapi.amap.com/v1/track/geofence/delete";
    /**
     * 递归获取围栏状态
     */
    private static final String LOCATION_STATUS = "https://tsapi.amap.com/v1/track/geofence/status/location";


    /**
     * 实例化HttpClient，发送http请求使用，可根据需要自行调参
     */
    private static HttpClient httpClient = HttpClient4Utils.createHttpClient(100, 20, 2000, 2000, 2000);


    @Override
    public ResponseData<String> addFence(FenceParam fenceParam) {
        Map<String, String> params = new HashMap<>(8);
        params.put("key", THIRDPARTY_CONFIG.getGaodeKey());
        params.put("sid", THIRDPARTY_CONFIG.getGaodeSid());
        params.put("name", String.format("%s-%s", fenceParam.getFenceName(), System.currentTimeMillis()));
        params.put("desc", fenceParam.getFenceName().trim());
        String url = "";
        // 圆形
        if (fenceParam.getFenceType().equals(0)) {
            url = CIRCLE_ADD;
            params.put("center", fenceParam.getCentreLng() + "," + fenceParam.getCentreLat());
            params.put("radius", fenceParam.getRadius().toString());
        }
        //多边形
        if (fenceParam.getFenceType().equals(1)) {
            url = POLYGON_ADD;
            params.put("points", fenceParam.getPoints());
        }
        try {
            String response = HttpClient4Utils.sendPost(httpClient, url, params, Consts.UTF_8);
            JsonNode jsonNode = JsonUtils.readNode(response);
            log.info("创建围栏结果{}", JsonUtils.toJSONString(jsonNode));
            int errcode = jsonNode.get("errcode").asInt();
            // 10000:成功
            if (10000 == errcode) {
                JsonNode data = jsonNode.get("data");
                return ResponseData.buildSuccessResponse(data.get("gfid").asText());
            }
            String errMsg = jsonNode.get("errmsg").asText();
            log.error("创建地理围栏失败:{}", errMsg);
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, errMsg);
        } catch (Exception e) {
            log.error("创建地理围栏异常", e);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, null);
    }

    @Override
    public ResponseData<Boolean> updateFence(FenceParam fenceParam) {
        Map<String, String> params = new HashMap<>(8);
        params.put("key", THIRDPARTY_CONFIG.getGaodeKey());
        params.put("sid", THIRDPARTY_CONFIG.getGaodeSid());
        params.put("name", String.format("%s-%s", fenceParam.getFenceName(), System.currentTimeMillis()));
        params.put("desc", fenceParam.getFenceName().trim());
        params.put("gfid", fenceParam.getFenceGid().trim());
        String url = "";
        //圆形
        if (fenceParam.getFenceType().equals(0)) {
            url = CIRCLE_UPDATE;
            params.put("center", fenceParam.getCentreLng() + "," + fenceParam.getCentreLat());
            params.put("radius", fenceParam.getRadius().toString());
        }
        //多边形
        if (fenceParam.getFenceType().equals(1)) {
            url = POLYGON_UPDATE;
            params.put("points", fenceParam.getPoints());
        }
        try {
            String response = HttpClient4Utils.sendPost(httpClient, url, params, Consts.UTF_8);
            JsonNode jsonNode = JsonUtils.readNode(response);
            log.info("更新围栏结果{}", JsonUtils.toJSONString(jsonNode));
            int errcode = jsonNode.get("errcode").asInt();
            // 10000:成功
            if (10000 != errcode) {
                String errMsg = jsonNode.get("errmsg").asText();
                log.error("更新地理围栏失败:{}", errMsg);
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, errMsg, Boolean.FALSE);
            }
        } catch (Exception e) {
            log.error("更新地理围栏异常", e);
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "更新地理围栏异常", Boolean.FALSE);
        }
        return ResponseData.buildSuccessResponse("更新围栏成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> deleteFence(String fenceGid) {
        Map<String, String> params = new HashMap<>(8);
        params.put("key", THIRDPARTY_CONFIG.getGaodeKey());
        params.put("sid", THIRDPARTY_CONFIG.getGaodeSid());
        params.put("gfids", fenceGid);
        try {
            String response = HttpClient4Utils.sendPost(httpClient, GEOFENCE_DELETE, params, Consts.UTF_8);
            JsonNode jsonNode = JsonUtils.readNode(response);
            log.info("删除围栏结果{}", JsonUtils.toJSONString(jsonNode));
            int errcode = jsonNode.get("errcode").asInt();
            // 0:成功
            if (10000 != errcode) {
                String errMsg = jsonNode.get("errmsg").asText();
                log.error("删除地理围栏失败:{}", errMsg);
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "删除失败：" + errMsg, Boolean.FALSE);
            }
        } catch (Exception e) {
            log.error("删除地理围栏异常", e);
        }
        return ResponseData.buildSuccessResponse("删除地理围栏成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<List<FenceVo>> statusFence(double lng, double lat, String diu) {
        StringBuilder builder = new StringBuilder(LOCATION_STATUS);
        builder.append("?key=").append(THIRDPARTY_CONFIG.getGaodeKey());
        builder.append("&sid=").append(THIRDPARTY_CONFIG.getGaodeSid());
        builder.append("&location=").append(lng + "," + lat);
        try {
            List<FenceVo> fenceVos = statusLocation(builder, 1, 100);
            if (CollectionUtils.isEmpty(fenceVos)) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "监控失败");
            }
            return ResponseData.buildSuccessResponse(fenceVos);
        } catch (IOException e) {
            log.info("地理围栏监控异常", e);
        }
        return ResponseData.buildSuccessResponse(Lists.newArrayList());

    }

    /**
     * 递归获取围栏状态
     *
     * @param builder
     * @param page
     * @param pageSize
     * @return
     * @throws IOException
     */
    private List<FenceVo> statusLocation(StringBuilder builder, Integer page, Integer pageSize) throws IOException {
        builder.append("&page=").append(page);
        builder.append("&pagesize=").append(pageSize);
        HttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(builder.toString());
        HttpResponse response = httpClient.execute(httpGet);
        JsonNode jsonNode = JsonUtils.readNode(StringUtils.trim(EntityUtils.toString(response.getEntity(), "UTF-8")));
        log.info("{}查询围栏状态结果{}", builder.toString(), JsonUtils.toJSONString(jsonNode));
        int errcode = jsonNode.get("errcode").asInt();
        if (!Objects.equals(errcode, 10000)) {
            String errMsg = jsonNode.get("errmsg").asText();
            log.error("{} 查询围栏状态结果错误:{}", builder.toString(), errMsg);
            return Lists.newArrayList();
        }
        JsonNode data = jsonNode.get("data");
        ArrayNode arrayNode = JsonUtils.readArray(data.get("results").toString());
        if (arrayNode.size() <= 0) {
            return Lists.newArrayList();
        }
        List<FenceVo> fenceVos = new ArrayList<>();
        for (JsonNode result : arrayNode) {
            FenceVo fenceVo = new FenceVo();
            fenceVo.setFenceGid(result.get("gfid").asText());
            fenceVo.setFenceName(result.get("gfname").asText());
            fenceVo.setStatus(result.get("in").asInt() == 1 ? "in" : "out");
            fenceVos.add(fenceVo);
        }
        int count = data.get("count").asInt();
        if (count == pageSize) {
            fenceVos.addAll(statusLocation(builder, page + 1, pageSize));
        }
        return fenceVos;
    }
}
